package com.tiny_wind.tiny_wind_diary.interceptor;

import com.auth0.jwt.interfaces.Claim;
import com.tiny_wind.tiny_wind_diary.model.TwErrorModel;
import com.tiny_wind.tiny_wind_diary.model.TwResultModel;
import com.tiny_wind.tiny_wind_diary.service.impl.UserServiceImpl;
import com.tiny_wind.tiny_wind_diary.utility.GaJJwtManager;
import com.tiny_wind.tiny_wind_diary.utility.GaJsonManager;
import com.tiny_wind.tiny_wind_diary.utility.GaLogManager;
import com.tiny_wind.tiny_wind_diary.utility.ResponseCodeManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;

public class TokenInterceptor implements HandlerInterceptor {
	private Logger logger = LogManager.getLogger(this.getClass());
	private static String TAG = "TokenIntercreptor";
	@Autowired
	private UserServiceImpl mService;
	/**
	 * 进入Controller之前的拦截.
	 * 进行判断Token有效性校验
	 * 1,token本身进行校验.
	 * 2,解析出来的userId和数据库里的token匹配,不匹配返回校验失败.
	 * 3,
	 * @param request
	 * @param response
	 * @param handler
	 * @return
	 * @throws Exception
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		GaLogManager.v_c(TAG,"PATH","preHandle");
		if(CorsUtils.isPreFlightRequest(request)) {
			return true;
		}
		String token = request.getHeader(GaJJwtManager.ms_authKey);
		String info = String.format("TokenIntercrept/preHandle1111,token is: %s", token);
		if (token == null) {
			logger.warn("TokenIntecrept/preHandle,no token.");
			// 重定向返回登录失败信息.
			// 该方法只能用get请求来处理.
			PrintWriter printWriter = response.getWriter();
			TwResultModel result = new TwResultModel<Object> ( ResponseCodeManager.errorCode_noToken,ResponseCodeManager.getCodeMessage(ResponseCodeManager.errorCode_noToken));
			String json = GaJsonManager.toJson(result);
			printWriter.print(json);
			response.flushBuffer();
			return false;
		} else {
			Map<String, Claim> map = null;
			try {
				map = GaJJwtManager.verifyToken(token);
//				map = GaJJwtManager.parseToken(token);
			} catch (Exception e) {
				//使用重定向,感觉不太方便.
//				String url = String.format("%s/User/NoToken?code=%d",request.getContextPath(), ResponseCodeManager.errorCode_expiredToken);
//				GaLogManager.v_c(TAG,"Path","token:%s is expired,redirect to: %s",token,url);
				//Question:不清楚这里为什么发送的请求是POST的.
//				response.sendRedirect(url);
				//直接返回Token过期提示.
				PrintWriter printWriter = response.getWriter();
				TwResultModel result = new TwResultModel<Object> ( ResponseCodeManager.errorCode_expiredToken,ResponseCodeManager.getCodeMessage(ResponseCodeManager.errorCode_expiredToken));
				String json = GaJsonManager.toJson(result);
				printWriter.print(json);
				response.flushBuffer();
				return false;
			}
			Claim claim = map.get("userId");
			Integer userId = claim.asInt();
			String _token = mService.searchToken(userId);
			if(_token == null || !_token.toLowerCase().equals(token.toLowerCase())) {
				PrintWriter printWriter = response.getWriter();
				TwResultModel result = new TwResultModel<Object> (TwErrorModel.InvalidToken());
				String json = GaJsonManager.toJson(result);
				printWriter.print(json);
				response.flushBuffer();
				return false;
			}
			info = String.format("TokenIntercrept/preHandle,parse token success,user id is: %d", userId);
			request.setAttribute("userId", userId);
			logger.info(info);
		}
		return true;
	}

	// 执行后
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
		String info = String.format("TokenIntercrept/postHandle");
		logger.info(info);
	}

	// 清理
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
		String info = String.format("TokenIntercrept/afterCompletion");
		logger.info(info);
	}

}
